package com.swiftride.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.swiftride.constants.GlobalExceptionCode;
import com.swiftride.feign.DriverFeign;
import com.swiftride.pojo.domain.*;
import com.swiftride.pojo.param.PricingParam;
import com.swiftride.pojo.result.DriverTodayInfoResult;
import com.swiftride.pojo.result.PricingResult;
import com.swiftride.pojo.result.SplitAccountResult;
import com.swiftride.result.R;
import com.swiftride.service.*;
import com.swiftride.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class IPricingServiceImpl implements IPricingService {

    @Autowired
    private IChargeRuleStartService chargeRuleStartService;

    @Autowired
    private IChargeRuleWaitService chargeRuleWaitService;

    @Autowired
    private IChargeRuleReturnService chargeRuleReturnService;

    @Autowired
    private IProfitsharingRuleBaseService profitSharingRuleBaseService;

    @Autowired
    private IProfitsharingRuleDeductService profitSharingRuleDeductService;

    @Autowired
    private DriverFeign driverFeign;


    @Override
    @Transactional
    public PricingResult pricing(PricingParam param) {
        //1.参数校验
        //2.业务校验
        //2.1 起步价规则
        int hour = DateUtil.hour(param.getStartTime(), true);
        ChargeRuleStart ruleStart = chargeRuleStartService.getOne(new LambdaQueryWrapper<ChargeRuleStart>()
                .le(ChargeRuleStart::getHourStart, hour)
                .ge(ChargeRuleStart::getHourEnd, hour));
        AssertUtil.isNotNull(ruleStart, GlobalExceptionCode.SERVICE_ERROR);
        //2.2 等待时间规则
        ChargeRuleWait ruleWait = chargeRuleWaitService.getOne(new LambdaQueryWrapper<ChargeRuleWait>()
                .eq(ChargeRuleWait::getEnable, 0));
        AssertUtil.isNotNull(ruleWait, GlobalExceptionCode.SERVICE_ERROR);
        //2.3 返程费用规则
        ChargeRuleReturn ruleReturn = chargeRuleReturnService.getOne(new LambdaQueryWrapper<ChargeRuleReturn>()
                .eq(ChargeRuleReturn::getEnable, 0));
        AssertUtil.isNotNull(ruleReturn, GlobalExceptionCode.SERVICE_ERROR);
        //3.业务实现
        PricingResult pricingResult = new PricingResult();
        //3.1路程费用计算
        //估算里程
        BigDecimal expectsMileage = param.getExpectsMileage();
        //起步里程
        BigDecimal baseMileage = ruleStart.getBaseMileage();
        pricingResult.setBaseMileage(baseMileage);
        //起步价
        BigDecimal baseMileageAmount = ruleStart.getAmount();
        pricingResult.setBaseMileageAmount(baseMileageAmount);
        //每公里费用
        BigDecimal exceedBaseMileageAmount = ruleStart.getExceedEveryKmAmount();
        pricingResult.setExceedBaseMileageAmount(exceedBaseMileageAmount);
        //估算金额
        BigDecimal mileageAmount = new BigDecimal(String.valueOf(baseMileageAmount));
        if (expectsMileage.compareTo(baseMileage) > 0) {
            //行驶金额 = 起步价 + (行驶里程 - 起步里程) * 每公里行驶费用
            mileageAmount = baseMileageAmount.add(expectsMileage.subtract(baseMileage).multiply(exceedBaseMileageAmount));
        }
        pricingResult.setMileageAmount(mileageAmount);
        //3.2等待费用
        //免费等待时间
        Integer freeBaseWaitingMinute = ruleWait.getFreeBaseWaitingMinute();
        pricingResult.setFreeBaseWaitingMinute(freeBaseWaitingMinute);
        //每分钟等待金额
        BigDecimal exceedEveryMinuteAmount = ruleWait.getExceedEveryMinuteAmount();
        pricingResult.setExceedEveryMinuteAmount(exceedEveryMinuteAmount);
        //3.3返程费用
        //免费返程费用
        BigDecimal freeBaseReturnMileage = ruleReturn.getFreeBaseReturnMileage();
        pricingResult.setFreeBaseReturnMileage(freeBaseReturnMileage);
        //每公里返程费用
        BigDecimal exceedEveryKmAmount = ruleReturn.getExceedEveryKmAmount();
        pricingResult.setExceedBaseReturnEveryKmAmount(exceedEveryKmAmount);
        //计算返程费用
        BigDecimal returnAmount = new BigDecimal("0");
        if (expectsMileage.compareTo(freeBaseReturnMileage) > 0) {
            //返程费用 = (返程里程 - 免费返程里程) * 每公里返程费用
            returnAmount = (expectsMileage.subtract(freeBaseReturnMileage)).multiply(exceedEveryKmAmount);
        }
        pricingResult.setReturnAmount(returnAmount);
        //总金额 = 行驶金额 + 等待金额 + 返程费用
        pricingResult.setOrderAmount(mileageAmount.add(returnAmount));
        return pricingResult;
    }

    @Override
    public SplitAccountResult splitAccount(BigDecimal realOrderAmount) {
        //1.获取司机今日数据
        R<DriverTodayInfoResult> result = driverFeign.getDriverTodayInfoDto();
        AssertUtil.isTrue(result.isSuccess(), GlobalExceptionCode.SERVICE_REQUEST_ERROR);
        DriverTodayInfoResult driverTodayInfoResult = result.getData();
        Integer todayCancel = driverTodayInfoResult.getTodayCancel();
        Integer todayComplaint = driverTodayInfoResult.getTodayComplaint();
        String openId = driverTodayInfoResult.getOpenId();
        //2.查询分账级别
        ProfitsharingRuleBase ruleBase = profitSharingRuleBaseService.getById(1);
        AssertUtil.isNotNull(ruleBase, GlobalExceptionCode.DATA_EXCEPTION);
        //取消订单罚款比例
        ProfitsharingRuleDeduct cancelDeduct = profitSharingRuleDeductService.getOne(new LambdaQueryWrapper<ProfitsharingRuleDeduct>()
                .ge(ProfitsharingRuleDeduct::getNumberFrom, todayCancel)
                .le(ProfitsharingRuleDeduct::getNumberTo, todayCancel)
                .eq(ProfitsharingRuleDeduct::getType, 0));
        BigDecimal cancelDeductRate = ObjectUtil.isNull(cancelDeduct) ?
                BigDecimal.ZERO : cancelDeduct.getDriverRatioDeduct();
        //顾客投诉罚款比例
        ProfitsharingRuleDeduct complaintDeduct = profitSharingRuleDeductService.getOne(new LambdaQueryWrapper<ProfitsharingRuleDeduct>()
                .ge(ProfitsharingRuleDeduct::getNumberFrom, todayComplaint)
                .le(ProfitsharingRuleDeduct::getNumberTo, todayComplaint)
                .eq(ProfitsharingRuleDeduct::getType, 1));
        BigDecimal complaintDeductRate = ObjectUtil.isNull(complaintDeduct) ?
                BigDecimal.ZERO : complaintDeduct.getDriverRatioDeduct();
        //3.计算分账金额
        SplitAccountResult splitAccountResult = new SplitAccountResult();
        BigDecimal driverRate = ruleBase.getDriverRatio().subtract(cancelDeductRate).subtract(complaintDeductRate);
        driverRate = driverRate.compareTo(BigDecimal.ZERO) > 0 ? driverRate : BigDecimal.ZERO;
        BigDecimal platformRate = BigDecimal.ONE.subtract(driverRate);
        splitAccountResult.setDriverRate(driverRate);
        splitAccountResult.setPlatformRate(platformRate);
        splitAccountResult.setDriverIncome(realOrderAmount.multiply(driverRate));
        splitAccountResult.setPlatformIncome(realOrderAmount.multiply(platformRate));
        splitAccountResult.setToUserOpenId(openId);
        return splitAccountResult;
    }
}
